package service

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"teacher-helper/dao"
	"teacher-helper/models"
	"teacher-helper/models/request"
	"teacher-helper/models/response"
)

func AddOneScore(Score models.SysScore) error {
	var student models.SysStudent
	dao.DB.Where(&models.SysStudent{StuID:Score.StuID}).First(&student)
	Score.Name = student.Name
	Score.ClassID = student.ClassID
	return dao.DB.Create(&Score).Error
}

func GetScoreList(queryInfo request.QueryInfo) (Scores []models.SysScore, total int, err error) {
	if queryInfo == (request.QueryInfo{}){
		err = dao.DB.Preload("Semester").Preload("Course").Preload("Student").Find(&Scores).Count(&total).Error
		return
	}
	if queryInfo.Query == "" {
		if queryInfo.CourseID != 0 {
			if queryInfo.SemesterID != 0 {
				if err = dao.DB.Model(&models.SysScore{}).Where("course_id = ? and semester_id = ?", queryInfo.CourseID, queryInfo.SemesterID).Count(&total).Error; err != nil {
					return
				}
				err = dao.DB.Where("course_id = ? and semester_id = ?", queryInfo.CourseID, queryInfo.SemesterID).Limit(queryInfo.PageSize).Offset((queryInfo.PageNum - 1) * queryInfo.PageSize).Preload("Semester").Preload("Course").Preload("Student").Find(&Scores).Error
				return
			} else {
				if err = dao.DB.Model(&models.SysScore{}).Where("course_id = ?",  queryInfo.CourseID).Count(&total).Error; err != nil {
					return
				}
				err = dao.DB.Debug().Where("course_id = ?",  queryInfo.CourseID).Limit(queryInfo.PageSize).Offset((queryInfo.PageNum - 1) * queryInfo.PageSize).Preload("Semester").Preload("Course").Preload("Student").Find(&Scores).Error
				return
			}
		} else {
			if queryInfo.SemesterID != 0 {
				if err = dao.DB.Model(&models.SysScore{}).Where("semester_id = ?",  queryInfo.SemesterID).Count(&total).Error; err != nil {
					return
				}
				err = dao.DB.Where("semester_id = ?",  queryInfo.SemesterID).Limit(queryInfo.PageSize).Offset((queryInfo.PageNum - 1) * queryInfo.PageSize).Preload("Semester").Preload("Course").Preload("Student").Find(&Scores).Error
				return
			} else {
				if err = dao.DB.Model(&models.SysScore{}).Count(&total).Error; err != nil {
					return
				}
				err = dao.DB.Model(&models.SysScore{}).Limit(queryInfo.PageSize).Offset((queryInfo.PageNum - 1) * queryInfo.PageSize).Preload("Semester").Preload("Course").Preload("Student").Find(&Scores).Error
				return
			}
		}
	} else {
		if queryInfo.CourseID != 0 {
			if queryInfo.SemesterID != 0 {
				if err = dao.DB.Model(&models.SysScore{}).Where(queryInfo.KeyWord+" like ? and course_id = ? and semester_id = ?", queryInfo.Query+"%", queryInfo.CourseID, queryInfo.SemesterID).Count(&total).Error; err != nil {
					return
				}
				err = dao.DB.Where(queryInfo.KeyWord+" like ? and course_id = ? and semester_id = ?", queryInfo.Query+"%", queryInfo.CourseID, queryInfo.SemesterID).Limit(queryInfo.PageSize).Offset((queryInfo.PageNum - 1) * queryInfo.PageSize).Preload("Semester").Preload("Course").Preload("Student").Find(&Scores).Error
				return
			} else {
				if err = dao.DB.Model(&models.SysScore{}).Where(queryInfo.KeyWord+" like ? and course_id = ?", queryInfo.Query+"%", queryInfo.CourseID).Count(&total).Error; err != nil {
					return
				}
				err = dao.DB.Where(queryInfo.KeyWord+" like ? and course_id = ?", queryInfo.Query+"%", queryInfo.CourseID).Limit(queryInfo.PageSize).Offset((queryInfo.PageNum - 1) * queryInfo.PageSize).Preload("Semester").Preload("Course").Preload("Student").Find(&Scores).Error
				return
			}
		} else {
			if queryInfo.SemesterID != 0 {
				if err = dao.DB.Model(&models.SysScore{}).Where(queryInfo.KeyWord+" like ? and semester_id = ?", queryInfo.Query+"%", queryInfo.SemesterID).Count(&total).Error; err != nil {
					return
				}
				err = dao.DB.Where(queryInfo.KeyWord+" like ? and semester_id = ?", queryInfo.Query+"%", queryInfo.SemesterID).Limit(queryInfo.PageSize).Offset((queryInfo.PageNum - 1) * queryInfo.PageSize).Preload("Semester").Preload("Course").Preload("Student").Find(&Scores).Error
				return
			} else {
				if err = dao.DB.Model(&models.SysScore{}).Where(queryInfo.KeyWord+" like ?", queryInfo.Query+"%").Count(&total).Error; err != nil {
					return
				}
				err = dao.DB.Where(queryInfo.KeyWord+" like ?", queryInfo.Query+"%").Limit(queryInfo.PageSize).Offset((queryInfo.PageNum - 1) * queryInfo.PageSize).Preload("Semester").Preload("Course").Preload("Student").Find(&Scores).Error
				return
			}
		}
	}
}

func GetScoreFilter(queryInfo request.QueryInfo)(Scores []models.SysScore, err error)  {
	if queryInfo == (request.QueryInfo{}){
		err = errors.New("参数获取有误！")
		return
	}
	semester_id_list := strings.Split(queryInfo.SemesterIds, ",")
	var score_list []models.SysScore
	var stu_score_map = make(map[int][]models.SysScore)
	var stu_score_semeter_map = make(map[string][]models.SysScore)
	if queryInfo.ClassID == 0 {
		var classList []int
		dao.DB.Model(&models.SysClass{}).Joins("left join sys_grades on sys_classes.grade_id = sys_grades.id").Where("sys_classes.major_id = ? and sys_grades.name = ?", queryInfo.MajorID, queryInfo.GradeName).Pluck("sys_classes.id", &classList)
		dao.DB.Model(&models.SysScore{}).Where("class_id in (?) and semester_id in (?) and score < 60", classList, semester_id_list).Preload("Semester").Preload("Course").Preload("Student").Find(&score_list)
	}else {
		dao.DB.Model(&models.SysScore{}).Where("class_id = ? and semester_id in (?) and score < 60", queryInfo.ClassID, semester_id_list).Preload("Semester").Preload("Course").Preload("Student").Find(&score_list)
	}
	if len(semester_id_list) >= 2 && queryInfo.MulSemesterFailNum != 0 {
		for _, score := range score_list{
			stu_score_map[score.StuID] = append(stu_score_map[score.StuID], score)
			stu_score_semeter_map[strconv.Itoa(score.StuID) + strconv.Itoa(score.SemesterID)] = append(stu_score_semeter_map[strconv.Itoa(score.StuID) + strconv.Itoa(score.SemesterID)], score)
		}
		res_stu_map := make(map[int]bool)
		for stu, scores := range stu_score_map{
			if len(scores) >= queryInfo.MulSemesterFailNum {
				Scores = append(Scores, scores...)
				res_stu_map[stu] = true
			}
		}
		for stu_sem, scores := range stu_score_semeter_map{
			if len(scores) >= queryInfo.OneSemesterFailNum {
				stu_id, _ := strconv.Atoi(stu_sem[:10])
				_, ok := res_stu_map[stu_id]
				if !ok {
					Scores = append(Scores, scores...)
				}
			}
		}
	} else {
		for _, score := range score_list{
			stu_score_semeter_map[strconv.Itoa(score.StuID) + strconv.Itoa(score.SemesterID)] = append(stu_score_semeter_map[strconv.Itoa(score.StuID) + strconv.Itoa(score.SemesterID)], score)
		}
		for stu, scores := range stu_score_semeter_map {
			if len(scores) >= queryInfo.OneSemesterFailNum {
				Scores = append(Scores, scores...)
			}
		}
	}
	return
}

func GetScoreSummary(queryInfo request.QueryInfo)(Scores []response.ScoreSummary, total int, err error)  {
	if queryInfo == (request.QueryInfo{}){
		err = errors.New("参数获取有误！")
		return
	}
	semester_id_list := strings.Split(queryInfo.SemesterIds, ",")
	if queryInfo.ClassID == 0 {
		var classList []int
		dao.DB.Model(&models.SysClass{}).Joins("left join sys_grades on sys_classes.grade_id = sys_grades.id").Where("sys_classes.major_id = ? and sys_grades.name = ?", queryInfo.MajorID, queryInfo.GradeName).Pluck("sys_classes.id", &classList)
		dao.DB.Model(&models.SysScore{}).Select("count(distinct(stu_id))").Where("semester_id in (?) and class_id in (?)", semester_id_list, classList).Count(&total)
		err = dao.DB.Model(&models.SysScore{}).Limit(queryInfo.PageSize).Offset((queryInfo.PageNum-1)*queryInfo.PageSize).Select("stu_id, sys_scores.name, sum(score) as total, TRUNCATE(avg(score),2) as mean, sys_classes.name as class_name,sys_semesters.name as semester_name").Joins("left join sys_classes on sys_scores.class_id = sys_classes.id").Joins("LEFT JOIN sys_semesters on sys_scores.semester_id = sys_semesters.id").Where("semester_id in (?) and class_id in (?)", semester_id_list, classList).Group("stu_id").Order("total desc").Scan(&Scores).Error
	}else {
		dao.DB.Model(&models.SysScore{}).Select("count(distinct(stu_id))").Where("semester_id in (?) and class_id = ?", semester_id_list, queryInfo.ClassID).Count(&total)
		err = dao.DB.Model(&models.SysScore{}).Limit(queryInfo.PageSize).Offset((queryInfo.PageNum-1)*queryInfo.PageSize).Select("stu_id, sys_scores.name, sum(score) as total, TRUNCATE(avg(score),2) as mean, sys_classes.name as class_name,sys_semesters.name as semester_name").Joins("left join sys_classes on sys_scores.class_id = sys_classes.id").Joins("LEFT JOIN sys_semesters on sys_scores.semester_id = sys_semesters.id").Where("semester_id in (?) and class_id = ?", semester_id_list, queryInfo.ClassID).Group("stu_id").Order("total desc").Scan(&Scores).Error
	}
	return
}

func UpdateScore(Score models.SysScore) error {
	Score.Student = models.SysStudent{}
	Score.Course = models.SysCourse{}
	Score.Semester = models.SysSemester{}
	return dao.DB.Save(&Score).Error
}

func DeleteScore(id int) error {
	return dao.DB.Delete(&models.SysScore{ID:id}).Error
}